package core;

import java.nio.ByteBuffer;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import interfaces.*;
import proxy.*;
import util.*;

public class Interface {

	// Procurador da interface
	private InterfaceProxy interfaceProxy;
	
	// Cria um arquivo de log para os tempos de execucao
    // Armazena o JobId + o tempo de execucao
	private FileLog timeExecLog;

	// Tempo de  execucao
	private ExecutionTime execTime;
	
	// Gerador automatico de identificadores
	private RandomIDGenerator requestIDGenerator;
	
	// Lista de trabalhadores
	private List<Worker> workersList;
	
	// Lista de mapas dos Jobs enviados
	private Map<String, IJob> sendJobsList;

	// Identificacao da interface
	private String interfaceId;
	
	public Interface(String interfaceId, InterfaceProxy interfaceProxy) {
		try {
			this.interfaceProxy = interfaceProxy;
			
			this.interfaceId = interfaceId;

			this.timeExecLog = new FileLog("ExecutionTime", this.getID());
			
			this.execTime = new ExecutionTime();
			
			this.requestIDGenerator = new RandomIDGenerator();
			
			// Cria uma lista de trabalhadores
			this.workersList = new LinkedList<Worker>();
			
			// Cria uma lista de tarefas enviadas
			this.sendJobsList = new LinkedHashMap<String, IJob>();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void jobResult(String workerId, String jobId, byte[] resultDescription) {
		// TODO Auto-generated method stub
		try {
			ByteBuffer b = ByteBuffer.wrap(resultDescription);
			
			IJob tempJob = this.sendJobsList.get(jobId);
			this.timeExecLog.print(workerId + "\t\t" + jobId + "\t\t" + tempJob.getNumero() + 
					"\t\t" + b.getLong() + "\t\t" + ((this.execTime.resume() - tempJob.getExecBegin()) / 1000.));
			
			b.rewind();
			// /////////////////////////////////////////////////////////////////
			System.out.println("Interface =>");
			System.out.println("\t Recebi JOB_RESULT");
			System.out.println("\t\t RESPOSTA FINAL");
			System.out.println("\t\t Worker: " + workerId);
			System.out.println("\t\t JobId: " + jobId);
			System.out.println("\t\t Resposta: " + b.getLong());
			System.out.println("\t\t Levou (s): " + (this.execTime.resume() - tempJob.getExecBegin()) / 1000. + "\n");
			// /////////////////////////////////////////////////////////////////
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void newWorker(String workerId, String channelDescription) {
		// TODO Auto-generated method stub
		try {
			/////////////////////////////////////////////////////////////////////////
			//System.out.println("Interface: " + this.getID() + " =>");
			//System.out.println("\t Recebi Msg. NEW_WORKER");
			//System.out.println("\t WORKERID: " + workerId);
			//System.out.println("\t CHANNELDESC: " + channelDescription +"\n");
			/////////////////////////////////////////////////////////////////////////
			
			if (!getID().equals(workerId)) {
					Worker worker = new Worker();

					worker.setID(workerId);
					worker.setChannelDesc(channelDescription);
					this.workersList.add(worker);
					this.interfaceProxy.managerConnect(channelDescription);
					this.interfaceProxy.bossContactSend();
					workSend();
			}	
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void nodeStatus(String workerId, float capacity, int workload, long updateDate) {
        // TODO Auto-generated method stub
        try {
                /////////////////////////////////////////////////////////////////////////
                //System.out.println("Interface: " + this.getID() + " =>");
                //System.out.println("\t Recebi Msg. NODE_STATUS \n");
                /////////////////////////////////////////////////////////////////////////
        } catch (Exception e) {
                e.printStackTrace();
        }
    }

	public String getID() {
		// TODO Auto-generated method stub
		return this.interfaceId;
	}


	public void setID(String id) {
		// TODO Auto-generated method stub
		this.interfaceId = id;
	}

	public void setRequestSize(int requestSize) {
		// TODO Auto-generated method stub
		
	}
	
	public void workSend() {
		int tam = 60;
		for (int i = 0; i < 1; i++) {
			try {
				int idJ = this.requestIDGenerator.nextID();
				String jobId = "job" + idJ;

				ByteBuffer buf = ByteBuffer.allocate(4);
				buf.putInt(tam);

				IJob job = new Fibo(buf.array());
				job.setID(jobId);

				this.interfaceProxy.newJobSend(job);
	
				// /////////////////////////////////////////////////////////////////
				System.out.println("Interface (" + this.getID() +") =>");
				System.out.println("\t Enviei : " + (i + 1) + ", JOBID: " + job.getID() + " de tamanho: " + job.getWorkload() +" (" + tam + ")" + "\n");
				// /////////////////////////////////////////////////////////////////
				
				++tam;

				job.setExecBegin(execTime.resume());
				this.sendJobsList.put(job.getID(), job);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}
